from ..attributes import *
from ..attributes import _
from ..memoized import *
from ..space import *


class Layout(Object):
    width    = Attribute(initiable = False, writable = True, changed = lambda self: self.clear_expand())
    height   = Attribute(initiable = False, writable = True, changed = lambda self: self.clear_expand())
    expand_x = Attribute(initiable = False, writable = True, changed = lambda self: self.clear_static())
    expand_y = Attribute(initiable = False, writable = True, changed = lambda self: self.clear_static())
    
    def clear_static(self):
        self._width  = None
        self._height = None
    
    def clear_expand(self):
        self._expand_x = None
        self._expand_y = None
        
    @property
    def size(self):
        return (self.width, self.height)
    
    @property
    def expand(self):
        return (self.expand_x, self.expand_y)

    @size.setter
    def set_size(self, size):
        self.width, self.height = size

    @expand.setter
    def set_expand(self, expand):
        self.expand_x, self.expand_y = expand

    @property
    def is_fixed(self):
        return (self.expand_x is self.expand_y is None)


class Style(Object):
    def apply_to(self, classes):
        pass


class RenderingArea(Object):
    primitive_source =_ (None)
    default_style    =_ (None)
    
    width  = Attribute()
    height = Attribute()
    
    classes = SetAttribute()
    style   = Attribute(initiable = False)
    binding = Attribute(initiable = False)
    
    @property
    @memoized
    def area(self):
        return Position(0, 0).extend_by(self.width, self.height)
    
    def style_for(self, primitive):
        if self.style is None:
            style = self.default_style()
        else:
            style = self.style()
        
        style.apply_to(primitive.classes)
        
        return style
    
    def bind(self, info, style = None):
        self.style   = style
        self.binding = info.display_with(self.primitive_source(self))
        self.binding.add_classes(*self.classes)
    
    def display(self, info, style = None):
        self.bind(info, style)
        self.reflow()
    
    def reflow(self):
        self.binding.set_area(self.area)
